package com.zenithmind.library.controller;

import com.zenithmind.common.result.PageResult;
import com.zenithmind.common.result.Result;
import com.zenithmind.library.pojo.dto.CategoryCreateDTO;
import com.zenithmind.library.pojo.dto.CategoryUpdateDTO;
import com.zenithmind.library.pojo.query.CategoryQuery;
import com.zenithmind.library.pojo.vo.CategoryVO;
import com.zenithmind.library.service.CategoryService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 图书分类管理控制器
 * 
 * @author ZenithMind
 * @since 2024-06-14
 */
@Slf4j
@RestController
@RequestMapping("/api/zenithMind/v1/categories")
@RequiredArgsConstructor
@Tag(name = "图书分类管理", description = "图书分类的增删改查操作")
public class LibraryCategoryController {

    private final CategoryService categoryService;

    @GetMapping
    @Operation(summary = "分页查询分类", description = "根据条件分页查询分类列表")
    @PreAuthorize("hasAuthority('library:category:query')")
    public Result<PageResult<CategoryVO>> getCategoryPage(@Valid CategoryQuery query) {
        log.info("分页查询分类，查询条件：{}", query);
        PageResult<CategoryVO> result = categoryService.getCategoryPage(query);
        return Result.success(result);
    }

    @GetMapping("/tree")
    @Operation(summary = "获取分类树", description = "获取分类树结构")
    public Result<List<CategoryVO>> getCategoryTree(
            @Parameter(description = "父分类ID") @RequestParam(required = false) String parentId) {
        log.info("获取分类树，父分类ID：{}", parentId);
        List<CategoryVO> result = categoryService.getCategoryTree(parentId);
        return Result.success(result);
    }

    @GetMapping("/tree/all")
    @Operation(summary = "获取所有分类树", description = "获取完整的分类树结构")
    public Result<List<CategoryVO>> getAllCategoryTree() {
        log.info("获取所有分类树");
        List<CategoryVO> result = categoryService.getAllCategoryTree();
        return Result.success(result);
    }

    @GetMapping("/{id}")
    @Operation(summary = "查询分类详情", description = "根据ID查询分类详细信息")
    @PreAuthorize("hasAuthority('library:category:query')")
    public Result<CategoryVO> getCategoryDetail(
            @Parameter(description = "分类ID", required = true) @PathVariable String id) {
        log.info("查询分类详情，ID：{}", id);
        CategoryVO result = categoryService.getCategoryDetail(id);
        return Result.success(result);
    }

    @PostMapping
    @Operation(summary = "创建分类", description = "新增分类信息")
    @PreAuthorize("hasAuthority('library:category:create')")
    public Result<CategoryVO> createCategory(@Valid @RequestBody CategoryCreateDTO createDTO) {
        log.info("创建分类，数据：{}", createDTO);
        return categoryService.createCategory(createDTO);
    }

    @PutMapping("/{id}")
    @Operation(summary = "更新分类", description = "更新分类信息")
    @PreAuthorize("hasAuthority('library:category:update')")
    public Result<CategoryVO> updateCategory(
            @Parameter(description = "分类ID", required = true) @PathVariable String id,
            @Valid @RequestBody CategoryUpdateDTO updateDTO) {
        log.info("更新分类，ID：{}，数据：{}", id, updateDTO);
        return categoryService.updateCategory(id, updateDTO);
    }

    @DeleteMapping("/{id}")
    @Operation(summary = "删除分类", description = "根据ID删除分类")
    @PreAuthorize("hasAuthority('library:category:delete')")
    public Result<Void> deleteCategory(
            @Parameter(description = "分类ID", required = true) @PathVariable String id) {
        log.info("删除分类，ID：{}", id);
        return categoryService.deleteCategory(id);
    }

    @DeleteMapping("/batch")
    @Operation(summary = "批量删除分类", description = "根据ID列表批量删除分类")
    @PreAuthorize("hasAuthority('library:category:delete')")
    public Result<Void> batchDeleteCategories(@RequestBody List<String> ids) {
        log.info("批量删除分类，IDs：{}", ids);
        return categoryService.batchDeleteCategories(ids);
    }

    @PutMapping("/{id}/enable")
    @Operation(summary = "启用分类", description = "将分类设置为启用状态")
    @PreAuthorize("hasAuthority('library:category:update')")
    public Result<Void> enableCategory(
            @Parameter(description = "分类ID", required = true) @PathVariable String id) {
        log.info("启用分类，ID：{}", id);
        return categoryService.enableCategory(id);
    }

    @PutMapping("/{id}/disable")
    @Operation(summary = "禁用分类", description = "将分类设置为禁用状态")
    @PreAuthorize("hasAuthority('library:category:update')")
    public Result<Void> disableCategory(
            @Parameter(description = "分类ID", required = true) @PathVariable String id) {
        log.info("禁用分类，ID：{}", id);
        return categoryService.disableCategory(id);
    }

    @GetMapping("/code/{code}")
    @Operation(summary = "根据编码查询分类", description = "根据分类编码查询分类信息")
    @PreAuthorize("hasAuthority('library:category:query')")
    public Result<CategoryVO> getCategoryByCode(
            @Parameter(description = "分类编码", required = true) @PathVariable String code) {
        log.info("根据编码查询分类，编码：{}", code);
        CategoryVO result = categoryService.getCategoryByCode(code);
        return Result.success(result);
    }

    @GetMapping("/{parentId}/children")
    @Operation(summary = "获取子分类", description = "根据父分类ID获取子分类列表")
    @PreAuthorize("hasAuthority('library:category:query')")
    public Result<List<CategoryVO>> getChildren(
            @Parameter(description = "父分类ID", required = true) @PathVariable String parentId) {
        log.info("获取子分类，父分类ID：{}", parentId);
        List<CategoryVO> result = categoryService.getChildren(parentId);
        return Result.success(result);
    }

    @PutMapping("/{id}/move")
    @Operation(summary = "移动分类", description = "将分类移动到新的父分类下")
    @PreAuthorize("hasAuthority('library:category:update')")
    public Result<Void> moveCategory(
            @Parameter(description = "分类ID", required = true) @PathVariable String id,
            @Parameter(description = "新父分类ID", required = true) @RequestParam String newParentId) {
        log.info("移动分类，ID：{}，新父分类ID：{}", id, newParentId);
        return categoryService.moveCategory(id, newParentId);
    }

    @PutMapping("/{id}/sort")
    @Operation(summary = "更新分类排序", description = "更新分类的排序号")
    @PreAuthorize("hasAuthority('library:category:update')")
    public Result<Void> updateCategorySortOrder(
            @Parameter(description = "分类ID", required = true) @PathVariable String id,
            @Parameter(description = "排序号", required = true) @RequestParam Integer sortOrder) {
        log.info("更新分类排序，ID：{}，排序号：{}", id, sortOrder);
        return categoryService.updateCategorySortOrder(id, sortOrder);
    }

    @GetMapping("/hot")
    @Operation(summary = "获取热门分类", description = "获取热门分类列表")
    public Result<List<CategoryVO>> getHotCategories(
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "10") Integer limit) {
        log.info("获取热门分类，限制数量：{}", limit);
        List<CategoryVO> result = categoryService.getHotCategories(limit);
        return Result.success(result);
    }

    @PutMapping("/{id}/book-count")
    @Operation(summary = "更新分类图书数量", description = "重新统计并更新分类的图书数量")
    @PreAuthorize("hasAuthority('library:category:update')")
    public Result<Void> updateCategoryBookCount(
            @Parameter(description = "分类ID", required = true) @PathVariable String id) {
        log.info("更新分类图书数量，分类ID：{}", id);
        return categoryService.updateCategoryBookCount(id);
    }

    @GetMapping("/check/code/{code}")
    @Operation(summary = "检查分类编码", description = "检查分类编码是否已存在")
    @PreAuthorize("hasAuthority('library:category:query')")
    public Result<Boolean> checkCategoryCode(
            @Parameter(description = "分类编码", required = true) @PathVariable String code,
            @Parameter(description = "排除的分类ID") @RequestParam(required = false) String excludeId) {
        log.info("检查分类编码，编码：{}，排除ID：{}", code, excludeId);
        boolean exists = categoryService.existsByCode(code, excludeId);
        return Result.success(!exists);
    }

    @GetMapping("/check/name")
    @Operation(summary = "检查分类名称", description = "检查分类名称是否已存在")
    @PreAuthorize("hasAuthority('library:category:query')")
    public Result<Boolean> checkCategoryName(
            @Parameter(description = "分类名称", required = true) @RequestParam String name,
            @Parameter(description = "父分类ID") @RequestParam(required = false) String parentId,
            @Parameter(description = "排除的分类ID") @RequestParam(required = false) String excludeId) {
        log.info("检查分类名称，名称：{}，父分类ID：{}，排除ID：{}", name, parentId, excludeId);
        boolean exists = categoryService.existsByName(name, parentId, excludeId);
        return Result.success(!exists);
    }

    @PostMapping("/import")
    @Operation(summary = "导入分类数据", description = "批量导入分类数据")
    @PreAuthorize("hasAuthority('library:category:import')")
    public Result<String> importCategories(@RequestBody List<CategoryCreateDTO> categories) {
        log.info("导入分类数据，数量：{}", categories.size());
        return categoryService.importCategories(categories);
    }

    @GetMapping("/export")
    @Operation(summary = "导出分类数据", description = "导出分类数据到Excel文件")
    @PreAuthorize("hasAuthority('library:category:export')")
    public Result<String> exportCategories(@Valid CategoryQuery query) {
        log.info("导出分类数据，查询条件：{}", query);
        return categoryService.exportCategories(query);
    }
}
